/*
 * gladegtk.cpp
 * 
 * Copyright 2012  <Santa Fe, Argentina>
 * 
 *  GladeGTK is a command line tool for create GTK+ Projects from Glade files. 
 * 
 * For contributions send a email to contacto@valorzi.com.ar
 * http://valorzi.com.ar
 * 
*/
#include <iostream>
#include <vector>
#include <iterator>
#include <string>
#include <cstring>
#include <fstream>
using namespace std;
class Componente{
public:
    string id;
    string clase;
    string nombre;
Componente(){id="";clase="";nombre="";}
};
    vector<Componente> L;
    vector<string> Evento;
string leerfichero(const char *url){
string Texto="";
try{
    
     string texto="";
    ifstream entrada(url);
 while(getline(entrada,texto))
 Texto=Texto+texto;
  entrada.close();
 
  }catch(...){cout<<"Error de Lectura"<<endl;}

  return Texto;
}
//-----------------------------------------------------------------------
void escribirfichero(char* url,char* s){
try{
  ofstream salida(url);
  salida<<s;
salida.close();  
}catch(...){cout<<"Error de Escritura"<<endl;}

}
//-------------------------------------------------------------------------
const string validar(string s){
    unsigned int n=s.length();
    for(unsigned int i=0;i<n;++i)
        if(s[i]=='-')s[i]='$';
    return s;
    }


void rellenarIds(string texto){

    int n=strlen(texto.c_str());
    for(int h=0;h<n-7;++h){
if(texto[h]=='c'&&texto[h+1]=='l'&&texto[h+2]=='a'&&texto[h+3]=='s'&&texto[h+4]=='s'&&texto[h+5]=='=')
{
    Componente comp;
    string Aux="";h+=7;
        for(int l=h;texto[l]!='"';++l)
        Aux=Aux+texto[l];
        comp.clase=Aux;    
        // Tipo.push_back(Aux);
    for(int i=h;i<n-4;++i){
        if(texto[i]=='i'&&texto[i+1]=='d'&&texto[i+2]=='=')
        {
        string aux="";
        for(int j=i+4;texto[j]!='"';++j)
        aux=aux+texto[j];    
        // Id.push_back(validar(aux));
        comp.nombre=aux;
        comp.id=validar(aux);
        
        i=n;
        }
        }
      L.push_back(comp);
      }
    }
}
void rellenarEventos(string texto){
    int n=strlen(texto.c_str());
    for(int i=0;i<n-8;++i){
        if(texto[i]=='h'&&texto[i+1]=='a'&&texto[i+2]=='n'&&texto[i+3]=='d'&&texto[i+4]=='l'&&texto[i+5]=='e'&&texto[i+6]=='r'&&texto[i+7]=='=')
        {
        string aux="";
        for(int j=i+9;texto[j]!='"';++j)
        aux=aux+texto[j];    
         Evento.push_back(aux);
        }
        }
    }
    const char* Ayuda(){
    return "GladeGTK is a command line tool for create cpp units from Glade files.\ncontacto@valorzi.com.ar\nhttp://valorzi.com.ar\n\n1) Create glade file with Glade designer (A window component is required)\n2) gladegtk *.glade\n3)Edit generated *.cpp\n4) Compile generated *.cpp (myFile) with command\ng++ -o myFile miFile.cpp $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0)\n";
    }
const char* Unidad(char *s){
    string aux="";
    int n=strlen(s);
    for(int i=n-1;i>0;--i)
    if(s[i]=='.')
    for(int j=0;j<i;++j)
    aux=aux+s[j];
    return aux.c_str();
    }
    void Completar(string url,char* gladeui);
int main(int argc, char **argv)
{
    if(argc<2){
        cout<<"glade file?"<<endl;
        return 0;
        }
        if(strcmp(argv[1],"--help")==0)
        {
        cout<<Ayuda()<<endl;
        return 0;    
        }
    string texto=leerfichero(argv[1]);
    rellenarIds(texto);
    rellenarEventos(texto);
    Completar(Unidad(argv[1]),argv[1]);
    return 0;
}
const char *Salir(string s,string s1){
if(s.compare("on_"+s1+"_destroy")==0)
return " gtk_main_quit ();";
return " ";    
    }
string Mayusc(string s){
    size_t n=s.length();
    for(unsigned int i=0;i<n;++i)
    if(s[i]>='a'&&s[i]<='z')s[i]=char(int(s[i])-32);
    else if(i>1&&s[i]>='A'&&s[i]<='Z'){if(s[i-2]!='_'){s.insert(i,"_");++i;++n;}}
    return s;
    }
const char* devCast(string s){
    if(s.length()>3)
    if(s[0]=='G'&&s[1]=='t'&&s[2]=='k'){
    return  Mayusc(s).c_str();}
    return s.c_str();
    }
bool Existe (string url){
  ifstream fin;
  fin.open (url.c_str());
  if (fin.fail()) return false;
  fin.close();
  return true;
}
void Agregar(string url,string window1)
{
    char cm='"';
fstream Salida;
Salida.open (url.c_str(), fstream::app);
for (vector<string>::iterator ite = Evento.begin(); ite!=Evento.end(); ++ite) 
Salida<<"extern "<<cm<<"C"<<cm<<" G_MODULE_EXPORT void "<<*ite<<"(GtkObject *caller, gpointer data){"<<endl<<Salir(*ite,window1)<<"}"<<endl;
Salida.close();
    
}
void Completar(string url,char* gladeui){
    vector<Componente>::iterator it = L.begin();
    string window1="";
  {
      bool continuar=true;
    for (it = L.begin(); it!=L.end()&&continuar; ++it) 
    if((*it).clase.compare("GtkWindow")==0){
    window1=(*it).id;continuar=false;
    }
}
try{
string url_h=url+".h";

  ofstream salida(url_h.c_str());
  char cm='"';
salida<<"/*"<<endl<<"* Creado con GladeGTK"<<endl<<"*"<<endl<<"*/"<<endl;
salida<<"#include <gtk/gtk.h>"<<endl<<endl<<"class MainWindow{"<<endl<<"private:"<<endl<<"    GtkBuilder *builder;"<<endl<<"public:"<<endl;
    
for (it = L.begin(); it!=L.end(); ++it)
    salida<<"    "<<(*it).clase<<"* "<<(*it).id<<";"<<endl;
salida<<endl<<"MainWindow(){}"<<endl<<"MainWindow(int argc,char **argv){"<<endl<<"GError *error = NULL;"<<endl<<"gtk_init( &argc, &argv );"<<endl<<"builder = gtk_builder_new();"<<endl<<"    if( ! gtk_builder_add_from_file( builder, "<<cm<<gladeui<<cm<<", &error ) )"<<endl<<"    {"<<endl<<"        g_warning( "<<cm<<"%s"<<cm<<", error->message );"<<endl<<"        g_free( error );"<<endl<<"    }"<<endl;    
for (it = L.begin(); it!=L.end(); ++it) 
    salida<<(*it).id<<"= "<<devCast((*it).clase)<<"( gtk_builder_get_object( builder,"<<cm<<(*it).nombre<<cm<<"));"<<endl;
salida<<"gtk_builder_connect_signals( builder, NULL );"<<endl<<"g_object_unref( G_OBJECT( builder ) );"<<endl;
if(window1.length()==0)salida<<"//";
salida<<"    gtk_widget_show(GTK_WIDGET("<<window1<<"));"<<endl<<"    }"<<endl<<"};"<<endl;

for (vector<string>::iterator ite = Evento.begin(); ite!=Evento.end(); ++ite) 
salida<<"extern "<<cm<<"C"<<cm<<" G_MODULE_EXPORT void "<<*ite<<"(GtkObject *caller, gpointer data);"<<endl;
salida.close();
cout<<url_h<<" ok"<<endl;
string url_cpp=url+".cpp";

if(!Existe(url_cpp)){
//
ofstream Salida(url_cpp.c_str());
Salida<<"/*"<<endl<<"* Creado con GladeGTK"<<endl<<"* Para Compilar: g++ -o "<<Unidad(gladeui)<<" "<<url_cpp.c_str()<<" $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0)"<<endl<<"*"<<endl<<"* Contenido(ej.):  gtk_label_set_text(ui.label1,"<<cm<<"texto"<<cm<<");"<<endl<<"*/"<<endl;
Salida<<"#include <gtk/gtk.h>"<<endl<<"#include "<<cm<<url_h<<cm<<endl<<endl;
Salida<<"MainWindow ui;     "<<endl<<"int main( int argc,char **argv )"<<endl<<"{"<<endl<<"   ui=MainWindow(argc,argv);"<<endl<<"   gtk_main();"<<endl<<"   return( 0 );"<<endl<<"}"<<endl;
for (vector<string>::iterator ite = Evento.begin(); ite!=Evento.end(); ++ite) 
Salida<<"extern "<<cm<<"C"<<cm<<" G_MODULE_EXPORT void "<<*ite<<"(GtkObject *caller, gpointer data){"<<endl<<Salir(*ite,window1)<<endl<<"}"<<endl;
Salida.close();
}else{
    string texto=leerfichero(url_cpp.c_str());

ofstream Salida(url_cpp.c_str(),ios::app);
for (vector<string>::iterator ite = Evento.begin(); ite!=Evento.end(); ++ite){ 
if(texto.find(*ite)==string::npos)
Salida<<"extern "<<cm<<"C"<<cm<<" G_MODULE_EXPORT void "<<*ite<<"(GtkObject *caller, gpointer data){"<<endl<<Salir(*ite,window1)<<endl<<"}"<<endl;    
}
Salida.close();    
    }
cout<<url_cpp<<" ok"<<endl;

}catch(...){cout<<"Error de Escritura"<<endl;}

}


